<template>
  <div class="lg-flowchart-renderer lg-auto-size">
    <div class="lg-flowchart-canvas" @mousedown="onmousedown" @contextmenu.prevent>
      <div class="lg-flowchart-zoom">
        <div class="lg-flowchart-zoom-out" :class="nowVal === 10 && 'disabled'" @click="zoomSize(1)"></div>
        <span>{{ nowVal }}%</span>
        <div class="lg-flowchart-zoom-in" :class="nowVal === 300 && 'disabled'" @click="zoomSize(2)"></div>
      </div>
      <div @scroll="onscroll" style="height: 100%;overflow: auto">
        <div
          class="lg-flowchart-box-scale"
          :class="{ 'lg-flowchart-viewer': disabled }"
          :style="`transform: scale(${nowVal / 100});`"
        >
          <node-box
            v-for="x in nodes"
            :key="x.key"
            :data="x"
            @click="click"
            @add-node="addNode"
            @del-node="delNode"
            @add-condition="addCondition"
            @del-condition="delCondition"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';
import NodeBox from './node.vue';
import type { AggregationGateway, ExclusiveGateway, Node } from './type';
import LgAutoSize from '@/soar/components/LgAutoSize/index.vue';

const props = defineProps<{
  data: Node[];
  disabled?: boolean;
}>();
const emit = defineEmits(['click', 'addNode', 'delNode', 'addCondition', 'delCondition']);

function handle(node: Node) {
  // 互斥网关
  if (node.type === 'exclusive-gateway') {
    let list = node.items;
    // 统计子节点数量
    let total = 0;
    for (const x of list) {
      // @ts-ignore
      x.total = 1;
      x.nodes = x.nodes.map(handle);
      for (const n of x.nodes) {
        if (n.type === 'exclusive-gateway' || n.type === 'aggregation-gateway') {
          // @ts-ignore
          x.total = n.total;
        }
      }
      // @ts-ignore
      total += x.total;
    }
    // 偏移和状态处理
    let pstatus = 0;
    let status = 0;
    let offset = 0;
    list = list.map((x: any) => {
      const diff = total / 2 - x.total / 2 - offset;
      offset += x.total;
      const active = x.nodes.filter((x: Node) => x.status > 0).length !== 0;
      const es = x.nodes[x.nodes.length - 1]?.status === 2;
      if (es) {
        status = 2;
        pstatus = 2;
      } else if (active) {
        status = 1;
      } else {
        status = 0;
      }
      x = {
        status,
        ...x,
      };
      if (diff > 0) {
        x.multiple = diff;
        x.position = 'left';
      } else if (diff === 0) {
        x.multiple = 0;
        x.position = 'center';
      } else {
        x.multiple = -diff;
        x.position = 'right';
      }
      return x;
    });
    if (status === 2) {
      for (const x of list) {
        // @ts-ignore
        if (x.status === 2) {
          continue;
        }
        // @ts-ignore
        x.status = 3;
        for (const node of x.nodes) {
          // @ts-ignore
          node.status = 3;
        }
      }
    }
    return {
      ...node,
      items: list,
      status: pstatus,
      total,
    } as ExclusiveGateway;
  }

  // 聚合网关
  if (node.type === 'aggregation-gateway') {
    let list = node.items;
    // 统计子节点数量
    let total = 0;
    for (const x of list) {
      // @ts-ignore
      x.total = 1;
      x.nodes = x.nodes.map(handle);
      for (const n of x.nodes) {
        if (n.type === 'exclusive-gateway' || n.type === 'aggregation-gateway') {
          // @ts-ignore
          x.total = n.total;
        }
      }
      // @ts-ignore
      total += x.total;
    }
    // 偏移和状态处理
    let status = 0;
    let offset = 0;
    list = list.map((x: any) => {
      const diff = total / 2 - x.total / 2 - offset;
      offset += x.total;
      const active = x.nodes.filter((x: Node) => x.status > 0).length !== 0;
      const es = x.nodes[x.nodes.length - 1]?.status === 2;
      if (es) {
        status = 2;
      } else if (active) {
        status = 1;
      } else {
        status = 0;
      }
      x = {
        status,
        ...x,
      };
      if (diff > 0) {
        x.multiple = diff;
        x.position = 'left';
      } else if (diff === 0) {
        x.multiple = 0;
        x.position = 'center';
      } else {
        x.multiple = -diff;
        x.position = 'right';
      }
      return x;
    });
    if (status === 2) {
      for (const x of list) {
        // @ts-ignore
        if (x.status === 2) {
          continue;
        }
        // @ts-ignore
        x.status = 3;
        for (const node of x.nodes) {
          // @ts-ignore
          node.status = 3;
        }
      }
    }
    return {
      ...node,
      items: list,
      status,
      total,
    } as AggregationGateway;
  }

  // 其他类型节点
  return node;
}
const nodes = computed(() => props.data?.map(handle));

const nowVal = ref(100);
function zoomSize(type: number) {
  if (type == 1) {
    if (nowVal.value == 10) {
      return;
    }
    nowVal.value -= 10;
  } else {
    if (nowVal.value == 300) {
      return;
    }
    nowVal.value += 10;
  }
}

function findC(e: HTMLElement): HTMLElement {
  if (e.classList.contains('lg-flowchart-canvas')) {
    return e;
  }
  if (e.parentElement === document.body || !e.parentElement) {
    return null;
  }
  return findC(e.parentElement);
}

const scrollbarRef = ref();
let startX = 0;
let startY = 0;
let position: any = {
  scrollTop: 0,
  scrollLeft: 0,
};
let el: any = null;
function onscroll(e: any) {
  position = e;
}
function mousemove(e: any) {
  scrollbarRef.value.scrollTo(startX - e.clientX, startY - e.clientY);
}
function onmousedown(e: any) {
  el = findC(e.target);
  if (e.button === 2 && el) {
    startX = e.clientX + position.scrollLeft;
    startY = e.clientY + position.scrollTop;
    document.removeEventListener('mousemove', mousemove);
    document.addEventListener('mousemove', mousemove);
    el.classList.add('lg-flowchart-move');
  }
}
document.addEventListener('mouseup', (e) => {
  document.removeEventListener('mousemove', mousemove);
  if (el) {
    el.classList.remove('lg-flowchart-move');
    el = null;
  }
});

function findNode(key: string, list: Node[]) {
  for (let i = 0; i < list.length; i++) {
    const node = list[i];
    if (node.key === key) {
      return node;
    }
    if (node.type === 'exclusive-gateway' || node.type === 'aggregation-gateway') {
      for (let j = 0; j < node.items.length; j++) {
        const item: any = node.items[j];
        if (item.key === key) {
          return item;
        }
        const res: any = findNode(key, item.nodes);
        if (res) {
          return res;
        }
      }
    }
  }
}

function click(d) {
  const node = findNode(d.key, props.data);
  emit('click', node);
}

function addNode(e) {
  e.data = findNode(e.data.key, props.data);
  emit('addNode', e);
}

function delNode(d) {
  const node = findNode(d.key, props.data);
  emit('delNode', node);
}

function addCondition(d) {
  emit('addCondition', findNode(d.key, props.data));
}

function delCondition(d) {
  d.gateway = findNode(d.gateway.key, props.data);
  emit('delCondition', d);
}
</script>

<style scoped lang="less">
.lg-flowchart-renderer {
  --head-c-bg: var(--td-brand-color-5);
  --head-c: #fff;
  --body-c-bg: #fff;
  --body-c: #000;
  --border: 1px solid #dcdfe6;
  --box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
  .lg-flowchart-canvas {
    background: var(--app-color-bg-secondary);
    height: 100%;
  }
  .lg-flowchart-zoom {
    display: flex;
    position: fixed;
    -webkit-box-align: center;
    -ms-flex-align: center;
    align-items: center;
    -webkit-box-pack: justify;
    -ms-flex-pack: justify;
    justify-content: space-between;
    height: 40px;
    width: 125px;
    right: 40px;
    margin-top: 30px;
    z-index: 10;
  }

  .lg-flowchart-zoom .lg-flowchart-zoom-in,
  .lg-flowchart-zoom .lg-flowchart-zoom-out {
    width: 30px;
    height: 30px;
    background: #fff;
    color: #c1c1cd;
    cursor: pointer;
    background-size: 100%;
    background-repeat: no-repeat;
  }

  .lg-flowchart-zoom .lg-flowchart-zoom-out {
    background-image: url(https://gw.alicdn.com/tfs/TB1s0qhBHGYBuNjy0FoXXciBFXa-90-90.png);
  }

  .lg-flowchart-zoom .lg-flowchart-zoom-out.disabled {
    opacity: 0.5;
  }

  .lg-flowchart-zoom .lg-flowchart-zoom-in {
    background-image: url(https://gw.alicdn.com/tfs/TB1UIgJBTtYBeNjy1XdXXXXyVXa-90-90.png);
  }

  .lg-flowchart-zoom .lg-flowchart-zoom-in.disabled {
    opacity: 0.5;
  }
  .lg-flowchart-box-scale {
    transform: scale(1);
    display: inline-block;
    position: relative;
    width: 100%;
    padding: 54.5px 0;
    -webkit-box-align: start;
    -ms-flex-align: start;
    align-items: flex-start;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
    min-width: -webkit-min-content;
    min-width: -moz-min-content;
    min-width: min-content;
    /*background-color: #f5f5f7;*/
    transform-origin: 50% 0px 0px;
  }
  .lg-flowchart-move {
    cursor: grabbing;
  }
}
:deep(.lg-flowchart-viewer .lg-node) {
  .lg-add-node,
  .lg-del-btn,
  .lg-condition-top {
    display: none !important;
  }
  .lg-line-vertical {
    height: 56px;
    min-height: 56px;
  }
}
</style>
